<template>
	<view class="app">
		<!-- canvas 等比例放大图片不变形 -->
		<canvas style="width:630rpx; height:986rpx;" canvas-id="firstCanvas"></canvas>
		<view class="btn" @click="chooseImage">上传图片 体验效果</view>
		<BottomTips txt="canvas画图 等比例放大 缩小 图片不变形" />
	</view>
</template>

<script>
	import BottomTips from '@/components/bottom-tips.vue'
	export default {
		components: {
			BottomTips
		},
		data() {
			return {
				topImg: '/static/poster/top-img.png',
				topImgInfo: {},																		// 获取的图片信息
				qrCode: '/static/poster/qrCode.png',
				avatar: '/static/poster/avatar.png',
				avatarInfo: {},
				stars: '/static/poster/stars.png'
			}
		},
		async mounted() {
			if(this.topImg != ''){
				this.topImgInfo = await this.getImageInfo(this.topImg)
				this.avatarInfo = await this.getImageInfo(this.avatar)
			}
			await this.initCanvas()
		},
		methods: {
			chooseImage(){
				uni.chooseImage({
					count: 1,
					sourceType: ['album'],
					success: async(res) => {
						console.log(res)
						this.topImg = res.tempFilePaths[0]
						this.topImgInfo = await this.getImageInfo(res.tempFilePaths[0])
						
						this.initCanvas()
					}
				});
			},
			// 获取图片信息
			getImageInfo(src){
				return new Promise((resolve, reject)=>{
					uni.getImageInfo({
						src,
						success: info=> { resolve( { width: info.width, height: info.height } )},
						fail: () => { reject(null) }
					})
				})
			},
			
			// 初始化canvs
			initCanvas() {
				let ctx = uni.createCanvasContext('firstCanvas');
				this.roundedRectangle(ctx, 0, 0, uni.upx2px(630), uni.upx2px(986), 16, '#ffffff')
				this.preventPictureDistortion(ctx,this.topImg,this.topImgInfo,0,0,uni.upx2px(630),uni.upx2px(572),0)
				
				this.roundedRectangle(ctx,0,0,uni.upx2px(630),uni.upx2px(112),0,'rgba(0,0,0,.5)')
				ctx.textAlign = 'center'
				ctx.setFontSize(uni.upx2px(36))
				ctx.fillStyle='#FDA858'
				ctx.fillText('邀请您参加集赞赢好礼',uni.upx2px(315),uni.upx2px(68))
				this.roundedRectangle(ctx,uni.upx2px(80),uni.upx2px(50),uni.upx2px(16),uni.upx2px(16),uni.upx2px(8),'#FDA858')
				this.roundedRectangle(ctx,uni.upx2px(536),uni.upx2px(50),uni.upx2px(16),uni.upx2px(16),uni.upx2px(8),'#FDA858')
				
				ctx.textAlign = 'left'
				ctx.setFontSize(uni.upx2px(32))
				ctx.fillStyle='#333333'
				this.textPrewrap(ctx,'寿司店又放大招了，这个暑假各种优惠活动，集赞满30个赞免费领取好礼！！！！',uni.upx2px(40),uni.upx2px(632),uni.upx2px(46),uni.upx2px(544),2)
				
				ctx.drawImage(this.qrCode,uni.upx2px(40),uni.upx2px(720),uni.upx2px(232),uni.upx2px(232));
				this.preventPictureDistortion(ctx,this.avatar,this.avatarInfo,uni.upx2px(302),uni.upx2px(740),uni.upx2px(80),uni.upx2px(80),uni.upx2px(38))
				ctx.drawImage(this.stars,uni.upx2px(474),uni.upx2px(766),uni.upx2px(108),uni.upx2px(28));
				
				ctx.setFontSize(uni.upx2px(28))
				this.textPrewrap(ctx,'百無禁忌',uni.upx2px(302),uni.upx2px(860),uni.upx2px(40),uni.upx2px(286),1)
				ctx.fillStyle='#3688FF'
				this.textPrewrap(ctx,'长按二维码识别送优惠',uni.upx2px(302),uni.upx2px(912),uni.upx2px(40),uni.upx2px(286),1)
				
				ctx.draw();
			},
			// 绘制圆角矩形
			roundedRectangle(ctx, x, y, width, height, r, color) {
				ctx.beginPath();
				ctx.moveTo(x + r, y);
				ctx.fillStyle = color; //矩形填充颜色
				ctx.lineTo(x + width - r, y);
				ctx.arc(x + width - r, y + r, r, Math.PI * 1.5, Math.PI * 2);
				ctx.lineTo(x + width, y + height - r);
				ctx.arc(x + width - r, y + height - r, r, 0, Math.PI * 0.5);
				ctx.lineTo(x + r, y + height);
				ctx.arc(x + r, y + height - r, r, Math.PI * 0.5, Math.PI);
				ctx.lineTo(x, y + r);
				ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5);
				ctx.fill();
			},


			// 文字自动换行  content文字  drawX:X轴坐标  drawY:Y轴坐标  lineHeight:文字高度  lineMaxWidth:文字宽度  lineNum:文字几行
			textPrewrap(ctx, content, drawX, drawY, lineHeight, lineMaxWidth, lineNum) {
				var drawTxt = ''; // 当前绘制的内容
				var drawLine = 1; // 第几行开始绘制
				var drawIndex = 0; // 当前绘制内容的索引
				// 判断内容是否可以一行绘制完毕
				if (ctx.measureText(content).width <= lineMaxWidth) {
					ctx.fillText(content, drawX, drawY);
				} else {
					for (var i = 0; i < content.length; i++) {
						drawTxt += content[i];
						if (ctx.measureText(drawTxt).width >= lineMaxWidth) {
							if (drawLine >= lineNum) {
								ctx.fillText(content.substring(drawIndex, i) + '..', drawX, drawY);
								break;
							} else {
								ctx.fillText(content.substring(drawIndex, i + 1), drawX, drawY);
								drawIndex = i + 1;
								drawLine += 1;
								drawY += lineHeight;
								drawTxt = '';
							}
						} else {
							// 内容绘制完毕，但是剩下的内容宽度不到lineMaxWidth
							if (i === content.length - 1) {
								ctx.fillText(content.substring(drawIndex), drawX, drawY);
							}
						}
					}
				}
			},
			
			// 图片变形解决方案  img:绘画的图片 imageAttributes:看情况可能是个数组 得到图片的属性  x y:图片的坐标 boxWidth:裁剪区域的宽 boxHeight:裁剪区域的高
			preventPictureDistortion(ctx,img,imageAttributes, x, y, boxWidth,boxHeight,r){
				let {width,height} = imageAttributes
				let imgScale = width / height   			// 图片的宽高比
				let imgW,imgH   											// 计算后得到图片的宽高
				let offsetW,offsetH										// 绘图时需要偏移的坐标
				
				imgH = boxHeight;imgW = imgScale * imgH;offsetW = (imgW-boxWidth) / 2;offsetH=0					// 开始计算图片宽高 以及偏移坐标
				if(imgW < boxWidth){imgW = boxWidth;imgH = imgW / imgScale; offsetH = (imgH-boxHeight) / 2; offsetW = 0}
				
				// 开始绘制 容纳图片的裁剪区域 
				ctx.save()
				ctx.beginPath()
				this.roundedRectangle(ctx, x, y, boxWidth, boxHeight, r,'#fff')
				ctx.clip()
				ctx.drawImage(img, x-offsetW, y-offsetH,imgW, imgH)
				ctx.restore()
			},
		}
	}
</script>

<style scoped lang="scss">
	.app {
		min-height: 100vh;
		display: flex;
		align-items: center;
		justify-content: center;
		flex-direction: column;
		background: #f8f8f8;
		.btn{height: 88rpx;line-height: 88rpx;background: #73acf1;color: #fff;font-size: 32rpx;padding: 0 20rpx;border-radius: 10rpx;margin-top: 20rpx;}
	}
</style>
